/*
 *  MiloInnovationCommon.cpp
 *  Milovo04alfa01
 *
 *  Created by Luca on 16/12/06.
 *  Copyright 2006 __MyCompanyName__. All rights reserved.
 *
 */

#include "MiloInnovation.h"

//Mil_Int SelectGoalThisAgent(vector<Mil_Int> &tmpVectIDAgentsToAnalize, Agents *tmpCurrentTabAgents, Recipes *tmpCurrentTabRecipes, 
//									 Artifacts *tmpCurrentTabArtifacts, Requests *tmpCurrentTabRequests, MilovoRandom &tmpCurrentMiloRand, 
//									 int tmpCurrentDebugLevel)
//{
//	Mil_Int tmpPrimaryIDAgent = tmpVectIDAgentsToAnalize[0];
//	// this vector is a set of artifact knowed by every agent saved in tmpVectIDAgentsToAnalize
//	vector<Mil_Int> VectIDArtifactKnowedByThoseAgents;
//	vector<Mil_Int> VectGoalSelectedFromRequest;
//	bool FlagGoalRequest = false;
//	// for every agent involved in this innovation tentative
//	for(vector<Mil_Int>::iterator tmpVectIDAgentsToAnalizeIter = tmpVectIDAgentsToAnalize.begin(); tmpVectIDAgentsToAnalizeIter != tmpVectIDAgentsToAnalize.end(); tmpVectIDAgentsToAnalizeIter++)
//	{
//		Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(*tmpVectIDAgentsToAnalizeIter);
//		if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabAgentsIter == tmpCurrentTabAgents->end()))
//		{
//			Mil_Int tmpCurrentIDAgent = *tmpVectIDAgentsToAnalizeIter;
//			cout << "Error in SelectGoalThisAgent function: cannot find tmpCurrentTabAgentsIter in tmpCurrentTabAgents: " << tmpCurrentIDAgent << endl;
//			exit(EXIT_FAILURE);
//		}
//		switch(tmpCurrentTabAgentsIter->second.Style.GetSelectGoalStrategy())
//		{
//			case 1:
//			{
//				// insert in VectIDArtifactKnowedByThoseAgents every artifact knowed by agent saved in tmpVectIDAgentsToAnalize
//				for(list<Mil_Int>::iterator LinkArtifactsKnowedThisAgentIter = tmpCurrentTabAgentsIter->second.LinkArtifactsKnowed.begin(); LinkArtifactsKnowedThisAgentIter != tmpCurrentTabAgentsIter->second.LinkArtifactsKnowed.end(); LinkArtifactsKnowedThisAgentIter++)
//				{
//					if(tmpCurrentDebugLevel >= 2)
//					{
//						Mil_Int tmpCurrentIDAgent = *tmpVectIDAgentsToAnalizeIter;
//						Mil_Int tmp_LinkArtifactsKnowedThisAgentIter = *LinkArtifactsKnowedThisAgentIter;
//						cout << "Inserting Artifact: " << tmp_LinkArtifactsKnowedThisAgentIter << " for agent: " << tmpCurrentIDAgent << endl;
//					}
//					// insert a knowed artifact only if exit in tmpCurrentTabArtifacts
//					Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->find(*LinkArtifactsKnowedThisAgentIter);
//					if(tmpCurrentTabArtifactsIter != tmpCurrentTabArtifacts->end())
//						VectIDArtifactKnowedByThoseAgents.push_back(*LinkArtifactsKnowedThisAgentIter);
//				}
//			}
//				break;
//			case 2:
//			{
//				VectIDArtifactKnowedByThoseAgents = ExtractAgentsOutputsName(tmpCurrentTabAgentsIter->second.GetID(), tmpCurrentTabAgents, 
//																								 tmpCurrentTabRecipes, tmpCurrentTabArtifacts, tmpCurrentDebugLevel);
//				if((tmpCurrentDebugLevel >= 0) && (VectIDArtifactKnowedByThoseAgents.size() <= 0)) 
//				{
//					cout << "VectIDArtifactKnowedByThoseAgentsSize: " << VectIDArtifactKnowedByThoseAgents.size() << endl;
//					exit(EXIT_FAILURE);
//				}
//			}
//				break;
//			case 3:
//			{
//				VectGoalSelectedFromRequest.push_back(SelectGoalFromRequest(tmpCurrentTabAgentsIter->second.GetID(), 
//																								tmpCurrentTabAgents, tmpCurrentTabRequests));
//				FlagGoalRequest = true;
//			}
//				break;
//		default:
//			break;
//		}
//	}
//	if(FlagGoalRequest == true)
//	{
//		if(VectGoalSelectedFromRequest.empty() == true)
//			return(0);
//		else return(VectGoalSelectedFromRequest[tmpCurrentMiloRand.GetIntRandom(0, (VectGoalSelectedFromRequest.size() - 1))]);
//	}
//	// if VectIDArtifactKnowedByThoseAgents is empty, then function must return false
//	// cause there is no artifact making base of innovation process: searching a goal.
//	if(VectIDArtifactKnowedByThoseAgents.empty() == true)
//		return(0);
//	// selecting an artifact as a base for imitation part of innovation
//	Mil_Int GoalSelected = 0;
//	bool FlagValideGoalFound = false;
//	//Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(tmpPrimaryIDAgent);
//	
//	vector<Mil_Int>::iterator VectIDArtifactKnowedByThoseAgentsIter = VectIDArtifactKnowedByThoseAgents.begin();
//	while((FlagValideGoalFound == false) && (VectIDArtifactKnowedByThoseAgentsIter != VectIDArtifactKnowedByThoseAgents.end()))
//	{
//		Mil_Int tmpIDArtifactSelected = VectIDArtifactKnowedByThoseAgents[tmpCurrentMiloRand.GetIntRandom(0, (VectIDArtifactKnowedByThoseAgents.size() - 1))];
//		Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->find(tmpIDArtifactSelected);
//		if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabArtifactsIter == tmpCurrentTabArtifacts->end()))
//		{
//			cout << "Error in SelectGoalThisAgent function: cannot find tmpCurrentTabArtifactsIter in tmpCurrentTabArtifacts: " << tmpIDArtifactSelected << endl;
//			exit(EXIT_FAILURE);
//		}
//		// extract artifact name of artifact selected for imitation part of innovation
//		Mil_Int tmpNameArtifactSelected = tmpCurrentTabArtifactsIter->second.GetName();
//		Mil_Double TempGoalSelected = static_cast<Mil_Double> (tmpNameArtifactSelected);
//		// check for Jump probability of this primary agent. If this agent may jump, artifact selected will
//		// multiply for a real random number close to a specific range given by agent's style parameters
//		Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(tmpPrimaryIDAgent);
//		if(tmpCurrentMiloRand.GetDoubleRandom(0.0, 1.0) <= tmpCurrentTabAgentsIter->second.Style.GetProbJump())
//			TempGoalSelected *= tmpCurrentMiloRand.GetDoubleRandom(tmpCurrentTabAgentsIter->second.Style.GetStartJumpRange(), tmpCurrentTabAgentsIter->second.Style.GetEndJumpRange());
//		GoalSelected = static_cast<Mil_Int> (TempGoalSelected);
//		if(CheckThisGoalWithAgentsOutputs(GoalSelected, tmpCurrentTabAgentsIter->second.GetID(), tmpCurrentTabAgents, tmpCurrentTabRecipes, 
//													 tmpCurrentTabArtifacts, tmpCurrentDebugLevel) == true)
//			FlagValideGoalFound = true;
//		else VectIDArtifactKnowedByThoseAgentsIter++;
//		
//		if(tmpCurrentTabAgentsIter->second.Style.GetUseDeepSearchGoal() == 0)
//			FlagValideGoalFound = true;
//	}
//	
//	if(FlagValideGoalFound == false)
//		GoalSelected = 0;
//	
//	if(tmpCurrentDebugLevel >= 2)
//		cout << "Agent " << tmpPrimaryIDAgent << " has select goal: " << GoalSelected << endl;
//
//	return(GoalSelected);
//}

//Mil_Int SelectGoalThisAgent(vector<Mil_Int> &tmpVectIDAgentsToAnalize, Agents *tmpCurrentTabAgents, Recipes *tmpCurrentTabRecipes, 
//									 Artifacts *tmpCurrentTabArtifacts, Requests *tmpCurrentTabRequests, MilovoRandom &tmpCurrentMiloRand, 
//									 int tmpCurrentDebugLevel)
//	{
//	Mil_Int tmpPrimaryIDAgent = tmpVectIDAgentsToAnalize[0];
//	// this vector is a set of artifact knowed by every agent saved in tmpVectIDAgentsToAnalize
//	vector<Mil_Int> VectIDArtifactKnowedByThoseAgents;
//	// for every agent involved in this innovation tentative
//	for(vector<Mil_Int>::iterator tmpVectIDAgentsToAnalizeIter = tmpVectIDAgentsToAnalize.begin(); tmpVectIDAgentsToAnalizeIter != tmpVectIDAgentsToAnalize.end(); tmpVectIDAgentsToAnalizeIter++)
//	{
//		Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(*tmpVectIDAgentsToAnalizeIter);
//		if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabAgentsIter == tmpCurrentTabAgents->end()))
//		{
//			Mil_Int tmpCurrentIDAgent = *tmpVectIDAgentsToAnalizeIter;
//			cout << "Error in SelectGoalThisAgent function: cannot find tmpCurrentTabAgentsIter in tmpCurrentTabAgents: " << tmpCurrentIDAgent << endl;
//			exit(EXIT_FAILURE);
//		}
//		// check if this agent select goal from his output or from his friends' output
//		if(tmpCurrentTabAgentsIter->second.Style.GetSelectGoalInAgentOutput() == 1)
//		{
//			VectIDArtifactKnowedByThoseAgents = ExtractAgentsOutputsName(tmpCurrentTabAgentsIter->second.GetID(), tmpCurrentTabAgents, 
//																							 tmpCurrentTabRecipes, tmpCurrentTabArtifacts, tmpCurrentDebugLevel);
//			if((tmpCurrentDebugLevel >= 0) && (VectIDArtifactKnowedByThoseAgents.size() <= 0)) 
//			{
//				cout << "VectIDArtifactKnowedByThoseAgentsSize: " << VectIDArtifactKnowedByThoseAgents.size() << endl;
//				exit(EXIT_FAILURE);
//			}
//		}
//		else
//		{
//			// insert in VectIDArtifactKnowedByThoseAgents every artifact knowed by agent saved in tmpVectIDAgentsToAnalize
//			for(list<Mil_Int>::iterator LinkArtifactsKnowedThisAgentIter = tmpCurrentTabAgentsIter->second.LinkArtifactsKnowed.begin(); LinkArtifactsKnowedThisAgentIter != tmpCurrentTabAgentsIter->second.LinkArtifactsKnowed.end(); LinkArtifactsKnowedThisAgentIter++)
//			{
//				if(tmpCurrentDebugLevel >= 2)
//				{
//					Mil_Int tmpCurrentIDAgent = *tmpVectIDAgentsToAnalizeIter;
//					Mil_Int tmp_LinkArtifactsKnowedThisAgentIter = *LinkArtifactsKnowedThisAgentIter;
//					cout << "Inserting Artifact: " << tmp_LinkArtifactsKnowedThisAgentIter << " for agent: " << tmpCurrentIDAgent << endl;
//				}
//				// insert a knowed artifact only if exit in tmpCurrentTabArtifacts
//				Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->find(*LinkArtifactsKnowedThisAgentIter);
//				if(tmpCurrentTabArtifactsIter != tmpCurrentTabArtifacts->end())
//					VectIDArtifactKnowedByThoseAgents.push_back(*LinkArtifactsKnowedThisAgentIter);
//			}
//		}
//	}
//	// if VectIDArtifactKnowedByThoseAgents is empty, then function must return false
//	// cause there is no artifact making base of innovation process: searching a goal.
//	if(VectIDArtifactKnowedByThoseAgents.empty() == true)
//		return(0);
//	// selecting an artifact as a base for imitation part of innovation
//	Mil_Int GoalSelected = 0;
//	bool FlagValideGoalFound = false;
//	//Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(tmpPrimaryIDAgent);
//	
//	vector<Mil_Int>::iterator VectIDArtifactKnowedByThoseAgentsIter = VectIDArtifactKnowedByThoseAgents.begin();
//	while((FlagValideGoalFound == false) && (VectIDArtifactKnowedByThoseAgentsIter != VectIDArtifactKnowedByThoseAgents.end()))
//	{
//		Mil_Int tmpIDArtifactSelected = VectIDArtifactKnowedByThoseAgents[tmpCurrentMiloRand.GetIntRandom(0, (VectIDArtifactKnowedByThoseAgents.size() - 1))];
//		Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->find(tmpIDArtifactSelected);
//		if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabArtifactsIter == tmpCurrentTabArtifacts->end()))
//		{
//			cout << "Error in SelectGoalThisAgent function: cannot find tmpCurrentTabArtifactsIter in tmpCurrentTabArtifacts: " << tmpIDArtifactSelected << endl;
//			exit(EXIT_FAILURE);
//		}
//		// extract artifact name of artifact selected for imitation part of innovation
//		Mil_Int tmpNameArtifactSelected = tmpCurrentTabArtifactsIter->second.GetName();
//		Mil_Double TempGoalSelected = static_cast<Mil_Double> (tmpNameArtifactSelected);
//		// check for Jump probability of this primary agent. If this agent may jump, artifact selected will
//		// multiply for a real random number close to a specific range given by agent's style parameters
//		Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(tmpPrimaryIDAgent);
//		if(tmpCurrentMiloRand.GetDoubleRandom(0.0, 1.0) <= tmpCurrentTabAgentsIter->second.Style.GetProbJump())
//			TempGoalSelected *= tmpCurrentMiloRand.GetDoubleRandom(tmpCurrentTabAgentsIter->second.Style.GetStartJumpRange(), tmpCurrentTabAgentsIter->second.Style.GetEndJumpRange());
//		GoalSelected = static_cast<Mil_Int> (TempGoalSelected);
//		if(CheckThisGoalWithAgentsOutputs(GoalSelected, tmpCurrentTabAgentsIter->second.GetID(), tmpCurrentTabAgents, tmpCurrentTabRecipes, 
//													 tmpCurrentTabArtifacts, tmpCurrentDebugLevel) == true)
//			FlagValideGoalFound = true;
//		else VectIDArtifactKnowedByThoseAgentsIter++;
//		
//		if(tmpCurrentTabAgentsIter->second.Style.GetUseDeepSearchGoal() == 0)
//			FlagValideGoalFound = true;
//	}
//	
//	if(FlagValideGoalFound == false)
//		GoalSelected = 0;
//	
//	if(tmpCurrentDebugLevel >= 2)
//		cout << "Agent " << tmpPrimaryIDAgent << " has select goal: " << GoalSelected << endl;
//	
//	return(GoalSelected);
//}

Mil_Int SelectGoalThisAgent(vector<Mil_Int> &tmpVectIDAgentsToAnalize, Agents *tmpCurrentTabAgents, Recipes *tmpCurrentTabRecipes, 
								Artifacts *tmpCurrentTabArtifacts, Requests *tmpCurrentTabRequests, MilovoRandom &tmpCurrentMiloRand, 
								MilovoEnvironment &tmp_CurrentMiloEnv)
{
		Mil_Int tmpPrimaryIDAgent = tmpVectIDAgentsToAnalize[0];
		// this vector is a set of artifact knowed by every agent saved in tmpVectIDAgentsToAnalize
		vector<Mil_Int> VectIDArtifactKnowedByThoseAgents;
		vector<Mil_Int> VectGoalSelectedFromRequest;
		bool FlagGoalRequest = false;
		// for every agent involved in this innovation tentative
		for(vector<Mil_Int>::iterator tmpVectIDAgentsToAnalizeIter = tmpVectIDAgentsToAnalize.begin(); tmpVectIDAgentsToAnalizeIter != tmpVectIDAgentsToAnalize.end(); tmpVectIDAgentsToAnalizeIter++)
		{
			Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(*tmpVectIDAgentsToAnalizeIter);
			if((tmp_CurrentMiloEnv.GetDebugLevel() >= 0) && (tmpCurrentTabAgentsIter == tmpCurrentTabAgents->end()))
			{
				Mil_Int tmpCurrentIDAgent = *tmpVectIDAgentsToAnalizeIter;
				cout << "Error in SelectGoalThisAgent function: cannot find tmpCurrentTabAgentsIter in tmpCurrentTabAgents: " << tmpCurrentIDAgent << endl;
				exit(EXIT_FAILURE);
			}
			
			if(tmpCurrentMiloRand.GetDoubleRandom(0.0, 1.0) <= tmpCurrentTabAgentsIter->second.Style.GetProbGoalFromRequest())
			{
				SelectGoalFromRequest(VectGoalSelectedFromRequest, tmpCurrentTabAgentsIter->second.GetID(), tmpCurrentTabAgents, tmpCurrentTabRequests, tmpCurrentMiloRand, tmp_CurrentMiloEnv);
				FlagGoalRequest = true;
			}
			else
			{
				// check if this agent select goal from his output or from his friends' output
				if(tmpCurrentTabAgentsIter->second.Style.GetSelectGoalInAgentOutput() == 1)
				{
					VectIDArtifactKnowedByThoseAgents = ExtractAgentsOutputsName(tmpCurrentTabAgentsIter->second.GetID(), tmpCurrentTabAgents, 
																				 tmpCurrentTabRecipes, tmpCurrentTabArtifacts, tmp_CurrentMiloEnv.GetDebugLevel());
					if((tmp_CurrentMiloEnv.GetDebugLevel() >= 0) && (VectIDArtifactKnowedByThoseAgents.size() <= 0)) 
					{
						cout << "VectIDArtifactKnowedByThoseAgentsSize: " << VectIDArtifactKnowedByThoseAgents.size() << endl;
						exit(EXIT_FAILURE);
					}
				}
				else
				{
					// insert in VectIDArtifactKnowedByThoseAgents every artifact knowed by agent saved in tmpVectIDAgentsToAnalize
					for(list<Mil_Int>::iterator LinkArtifactsKnowedThisAgentIter = tmpCurrentTabAgentsIter->second.LinkArtifactsKnowed.begin(); LinkArtifactsKnowedThisAgentIter != tmpCurrentTabAgentsIter->second.LinkArtifactsKnowed.end(); LinkArtifactsKnowedThisAgentIter++)
					{
						if(tmp_CurrentMiloEnv.GetDebugLevel() >= 2)
						{
							Mil_Int tmpCurrentIDAgent = *tmpVectIDAgentsToAnalizeIter;
							Mil_Int tmp_LinkArtifactsKnowedThisAgentIter = *LinkArtifactsKnowedThisAgentIter;
							cout << "Inserting Artifact: " << tmp_LinkArtifactsKnowedThisAgentIter << " for agent: " << tmpCurrentIDAgent << endl;
						}
						// insert a knowed artifact only if exit in tmpCurrentTabArtifacts
						Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->find(*LinkArtifactsKnowedThisAgentIter);
						if(tmpCurrentTabArtifactsIter != tmpCurrentTabArtifacts->end())
							VectIDArtifactKnowedByThoseAgents.push_back(*LinkArtifactsKnowedThisAgentIter);
					}
				}
			}
		}

		if(FlagGoalRequest == true)
		{
			if(VectGoalSelectedFromRequest.empty() == true)
				return(0);
			else
			{
				Mil_Int IDRequestSelected = VectGoalSelectedFromRequest[tmpCurrentMiloRand.GetIntRandom(0, (VectGoalSelectedFromRequest.size() - 1))];
				Requests::iterator tmpCurrentTabRequestsIter = tmpCurrentTabRequests->find(IDRequestSelected);
				if((tmp_CurrentMiloEnv.GetDebugLevel() >= 0) && (tmpCurrentTabRequestsIter == tmpCurrentTabRequests->end()))
				{
					cout << "error in SelectGoalThisAgent function: cannot find tmpCurrentTabRequestsIter in tmpCurrentTabRequests: " << IDRequestSelected << endl;
					exit(EXIT_FAILURE);
				}
				Agents::iterator tmpCurrentTabAgentsKeepRequestIter = tmpCurrentTabAgents->find(tmpPrimaryIDAgent);
				tmpCurrentTabAgentsKeepRequestIter->second.SetIDTempRequest(tmpCurrentTabRequestsIter->second.GetID());
				
				return(tmpCurrentTabRequestsIter->second.GetArtifactName());
			}
		}
		// if VectIDArtifactKnowedByThoseAgents is empty, then function must return false
		// cause there is no artifact making base of innovation process: searching a goal.
		if(VectIDArtifactKnowedByThoseAgents.empty() == true)
			return(0);
		// selecting an artifact as a base for imitation part of innovation
		Mil_Int GoalSelected = 0;
		bool FlagValideGoalFound = false;		
		vector<Mil_Int>::iterator VectIDArtifactKnowedByThoseAgentsIter = VectIDArtifactKnowedByThoseAgents.begin();
		while((FlagValideGoalFound == false) && (VectIDArtifactKnowedByThoseAgentsIter != VectIDArtifactKnowedByThoseAgents.end()))
		{
			Mil_Int tmpIDArtifactSelected = VectIDArtifactKnowedByThoseAgents[tmpCurrentMiloRand.GetIntRandom(0, (VectIDArtifactKnowedByThoseAgents.size() - 1))];
			Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->find(tmpIDArtifactSelected);
			if((tmp_CurrentMiloEnv.GetDebugLevel() >= 0) && (tmpCurrentTabArtifactsIter == tmpCurrentTabArtifacts->end()))
			{
				cout << "Error in SelectGoalThisAgent function: cannot find tmpCurrentTabArtifactsIter in tmpCurrentTabArtifacts: " << tmpIDArtifactSelected << endl;
				exit(EXIT_FAILURE);
			}
			// extract artifact name of artifact selected for imitation part of innovation
			Mil_Int tmpNameArtifactSelected = tmpCurrentTabArtifactsIter->second.GetName();
			Mil_Double TempGoalSelected = static_cast<Mil_Double> (tmpNameArtifactSelected);
			// check for Jump probability of this primary agent. If this agent may jump, artifact selected will
			// multiply for a real random number close to a specific range given by agent's style parameters
			Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(tmpPrimaryIDAgent);
			if(tmpCurrentMiloRand.GetDoubleRandom(0.0, 1.0) <= tmpCurrentTabAgentsIter->second.Style.GetProbJump())
				TempGoalSelected *= tmpCurrentMiloRand.GetDoubleRandom(tmpCurrentTabAgentsIter->second.Style.GetStartJumpRange(), tmpCurrentTabAgentsIter->second.Style.GetEndJumpRange());
			GoalSelected = static_cast<Mil_Int> (TempGoalSelected);
			if(CheckThisGoalWithAgentsOutputs(GoalSelected, tmpCurrentTabAgentsIter->second.GetID(), tmpCurrentTabAgents, tmpCurrentTabRecipes, 
											  tmpCurrentTabArtifacts, tmp_CurrentMiloEnv.GetDebugLevel()) == true)
				FlagValideGoalFound = true;
			else VectIDArtifactKnowedByThoseAgentsIter++;
			
			if(tmpCurrentTabAgentsIter->second.Style.GetUseDeepSearchGoal() == 0)
				FlagValideGoalFound = true;
		}
		
		if(FlagValideGoalFound == false)
			GoalSelected = 0;
		
		if(tmp_CurrentMiloEnv.GetDebugLevel() >= 2)
			cout << "Agent " << tmpPrimaryIDAgent << " has select goal: " << GoalSelected << endl;
		
		return(GoalSelected);
}

bool InitGeneticPopulationRecipes(MilinitParams &tmpCurrentInitParam, SystemParams &tmpCurrentMilovoParam, GeneticRecipes &tmpTabGeneticPopulationRecipes, 
											 vector<Mil_Int> &tmpVectIDAgentsToAnalize, Agents *tmpCurrentTabAgents, Recipes *tmpCurrentTabRecipes, 
											 Artifacts *tmpCurrentTabArtifacts, MilovoRandom &CurrentMiloRand, int tmpCurrentDebugLevel)
{
	bool InitGeneticPopulationRecipesFlag = false;
	
	vector<Mil_Int> VectIDArtifactKnowedByThoseAgents;
	vector<Mil_Int> VectRecipeProduced;
	vector<Mil_Int> VectIDArtifactToDeny;
	for(vector<Mil_Int>::iterator tmpVectIDAgentsToAnalizeIter = tmpVectIDAgentsToAnalize.begin(); tmpVectIDAgentsToAnalizeIter != tmpVectIDAgentsToAnalize.end(); tmpVectIDAgentsToAnalizeIter++)
	{
		Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(*tmpVectIDAgentsToAnalizeIter);
		if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabAgentsIter == tmpCurrentTabAgents->end()))
		{
			Mil_Int tmpCurrentIDAgent = *tmpVectIDAgentsToAnalizeIter;
			cout << "Error in InitGeneticPopulationRecipes function: cannot find tmpCurrentTabAgentsIter in tmpCurrentTabAgents: " << tmpCurrentIDAgent << endl;
			exit(EXIT_FAILURE);
		}
		if(tmpCurrentDebugLevel >= 2)
			cout << "InitGeneticPopulationRecipes [fill VectRecipeProduced begin] for agent: " << tmpCurrentTabAgentsIter->second.GetID() << endl;
		// check for recipe produced by this agent
		for(list<Mil_Int>::iterator LinkRecipesIter = tmpCurrentTabAgentsIter->second.LinkRecipes.begin(); LinkRecipesIter != tmpCurrentTabAgentsIter->second.LinkRecipes.end(); LinkRecipesIter++)
		{
			Recipes::iterator tmpCurrentTabRecipesIter = tmpCurrentTabRecipes->find(*LinkRecipesIter);
			if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabRecipesIter == tmpCurrentTabRecipes->end()))
			{
				cout << "Error in InitGeneticPopulationRecipes function: cannot find tmpCurrentTabRecipesIter in tmpCurrentTabRecipes" << endl;
				exit(EXIT_FAILURE);
			}
			if(tmpCurrentTabRecipesIter->second.GetStatus() == tmpCurrentMilovoParam.GetMaxLifeRecipes())
			{
				VectRecipeProduced.push_back(tmpCurrentTabRecipesIter->second.GetID());
				if(tmpCurrentDebugLevel >= 2)
					cout << "Insert in VectRecipeProduced IDRecipe: " << tmpCurrentTabRecipesIter->second.GetID() << " of agent: " << tmpCurrentTabAgentsIter->second.GetID() << endl;
			}
			VectIDArtifactToDeny.push_back(tmpCurrentTabRecipesIter->second.GetIDArtifactOutput());
			if(tmpCurrentDebugLevel >= 2)
				cout << "Insert in VectIDArtifactToDeny IDOutput: " << tmpCurrentTabRecipesIter->second.GetIDArtifactOutput() << endl;
		}
		if(tmpCurrentDebugLevel >= 2)
			cout << "InitGeneticPopulationRecipes [fill VectRecipeProduced end] for agent: " << tmpCurrentTabAgentsIter->second.GetID() << endl;
	}
	// check for existing artifact knowed by this agent
	for(vector<Mil_Int>::iterator tmpVectIDAgentsToAnalizeIter = tmpVectIDAgentsToAnalize.begin(); tmpVectIDAgentsToAnalizeIter != tmpVectIDAgentsToAnalize.end(); tmpVectIDAgentsToAnalizeIter++)
	{
		Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(*tmpVectIDAgentsToAnalizeIter);
		if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabAgentsIter == tmpCurrentTabAgents->end()))
		{
			Mil_Int tmpCurrentIDAgent = *tmpVectIDAgentsToAnalizeIter;
			cout << "Error in InitGeneticPopulationRecipes function: cannot find tmpCurrentTabAgentsIter in tmpCurrentTabAgents: " << tmpCurrentIDAgent << endl;
			exit(EXIT_FAILURE);
		}
		if(tmpCurrentDebugLevel >= 2)
			cout << "InitGeneticPopulationRecipes [fill VectIDArtifactKnowedByThoseAgents begin] for agent: " << tmpCurrentTabAgentsIter->second.GetID() << endl;
		if(tmpCurrentDebugLevel >= 2)
			cout << "List of Knowed artifacts by those agents" << endl;
		for(list<Mil_Int>::iterator LinkArtifactsKnowedThisAgentIter = tmpCurrentTabAgentsIter->second.LinkArtifactsKnowed.begin(); LinkArtifactsKnowedThisAgentIter != tmpCurrentTabAgentsIter->second.LinkArtifactsKnowed.end(); LinkArtifactsKnowedThisAgentIter++)
		{
			Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->find(*LinkArtifactsKnowedThisAgentIter);
			if(tmpCurrentTabArtifactsIter != tmpCurrentTabArtifacts->end())
			{
				bool FlagDenyArtifactFound = false;
				vector<Mil_Int>::iterator VectIDArtifactToDenyIter = VectIDArtifactToDeny.begin();
				while((FlagDenyArtifactFound == false) && (VectIDArtifactToDenyIter != VectIDArtifactToDeny.end()))
				{
					Mil_Int tmpIDArtifactDenyToCompare = *VectIDArtifactToDenyIter;
					if(tmpCurrentDebugLevel >= 2)
						cout << "Compare tmpCurrentTabArtifactsIter->second.GetID(): " << tmpCurrentTabArtifactsIter->second.GetID() << " with tmpIDArtifactDenyToCompare: " << tmpIDArtifactDenyToCompare << endl; 
					if(tmpCurrentTabArtifactsIter->second.GetID() == tmpIDArtifactDenyToCompare)
						FlagDenyArtifactFound = true;
					else VectIDArtifactToDenyIter++;
				}
				if(FlagDenyArtifactFound == false)
				{
					VectIDArtifactKnowedByThoseAgents.push_back(tmpCurrentTabArtifactsIter->second.GetID());
					if(tmpCurrentDebugLevel >= 2)
						cout << "Insert in VectIDArtifactKnowedByThoseAgents IDArt: " << VectIDArtifactKnowedByThoseAgents[VectIDArtifactKnowedByThoseAgents.size() - 1] << endl;
				}
			}
		}
		if(tmpCurrentDebugLevel >= 2)
			cout << "InitGeneticPopulationRecipes [fill VectIDArtifactKnowedByThoseAgents end] for agent: " << tmpCurrentTabAgentsIter->second.GetID() << endl;
		if(tmpCurrentDebugLevel >= 2)
			cout << endl;
	}
	// if agent hasn't artifacts knowed or a recipe that it produced before innovation, it cannot try to innovate.
	if((VectIDArtifactKnowedByThoseAgents.empty() == true) || (VectRecipeProduced.empty() == true) || (VectIDArtifactToDeny.empty() == true))
	{
		if(tmpCurrentDebugLevel >= 2)
		{
			cout << "InitGeneticPopulationRecipes exit with false cause: " << endl;
			cout << "\tVectIDArtifactKnowedByThoseAgents.empty(): " << VectIDArtifactKnowedByThoseAgents.empty() << endl;
			cout << "\tVectRecipeProduced.empty(): " << VectRecipeProduced.empty() << endl;
			cout << "\tVectIDArtifactToDeny.empty(): " << VectIDArtifactToDeny.empty() << endl;
		}
		return(false);
	}
	// create the initial population. First a cycle for every individual of population
	for(Mil_Int HowManyIndividuals = 1; HowManyIndividuals <= tmpCurrentMilovoParam.GetNumGeneticRecipesForInitPopulation(); HowManyIndividuals++)
	{
		if(tmpCurrentDebugLevel >= 2)
			cout << "---> Init Genetic Population with individual n." << HowManyIndividuals << "--- [Begin] ---" << endl;
		// select randomly one recipe from agent's recipes park
		Mil_Int tmpRandRecipe = VectRecipeProduced[CurrentMiloRand.GetIntRandom(0, (VectRecipeProduced.size() - 1))];
		Recipes::iterator tmpCurrentTabRecipesIter = tmpCurrentTabRecipes->find(tmpRandRecipe);
		if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabRecipesIter == tmpCurrentTabRecipes->end()))
		{
			cout << "Error in InitGeneticPopulationRecipes function: cannot find tmpCurrentTabRecipesIter in tmpCurrentTabRecipes" << endl;
			exit(EXIT_FAILURE);
		}
		if(tmpCurrentDebugLevel >= 3)
			cout << "Selecting IDRecipe: " << tmpCurrentTabRecipesIter->second.GetID() << " of agent: " << tmpCurrentTabRecipesIter->second.GetIDAgentOwner() << endl;
//		bool FlagFoundValidRecipe = false;
//		while(FlagFoundValidRecipe == false)
//		{
			list<Mil_Int> tmpListIDInputs;
			for(list<Mil_Int>::iterator LinksIDArtifactsIter = tmpCurrentTabRecipesIter->second.LinksIDArtifacts.begin(); LinksIDArtifactsIter != tmpCurrentTabRecipesIter->second.LinksIDArtifacts.end(); LinksIDArtifactsIter++)
			{
				Mil_Int tmpIDInputToAnalize = *LinksIDArtifactsIter;
				if(tmpCurrentDebugLevel >= 3)
					cout << "checking for tmpIDInputToAnalize: " << tmpIDInputToAnalize << endl;
				// check if the artifact is one of those artifact output of agents partners
				bool FlagDenyArtifactFound = false;
				vector<Mil_Int>::iterator VectIDArtifactToDenyIter = VectIDArtifactToDeny.begin();
				while((FlagDenyArtifactFound == false) && (VectIDArtifactToDenyIter != VectIDArtifactToDeny.end()))
				{
					Mil_Int tmpIDArtifactDenyToCompare = *VectIDArtifactToDenyIter;
					if(tmpCurrentDebugLevel >= 3)
						cout << "Compare tmpIDInputToAnalize: " << tmpIDInputToAnalize << " with tmpIDArtifactDenyToCompare: " << tmpIDArtifactDenyToCompare << endl; 
					if(tmpIDInputToAnalize == tmpIDArtifactDenyToCompare)
					{
						FlagDenyArtifactFound = true;
						if(tmpCurrentDebugLevel >= 3)
							cout << "found tmpIDInputToAnalize: " << tmpIDInputToAnalize << " equal to tmpIDArtifactDenyToCompare: " << tmpIDArtifactDenyToCompare << endl;
					}
					VectIDArtifactToDenyIter++;
				}
				// if we must substitute cause artifact deny or cause change probability
				if((CurrentMiloRand.GetDoubleRandom(0.0, 1.0) <= tmpCurrentMilovoParam.GetProbGAInitPopulation()) || (FlagDenyArtifactFound == true))
				{
					bool FlagIDArtifactSostitutiveFound = false;
//					random_shuffle(VectIDArtifactKnowedByThoseAgents.begin(), VectIDArtifactKnowedByThoseAgents.end());
					vector<Mil_Int>::iterator VectIDArtifactKnowedByThoseAgentsIter = VectIDArtifactKnowedByThoseAgents.begin();
					while((FlagIDArtifactSostitutiveFound == false) && (VectIDArtifactKnowedByThoseAgentsIter != VectIDArtifactKnowedByThoseAgents.end()))
					{
						Mil_Int tmpRandomIDArtifactSelected = VectIDArtifactKnowedByThoseAgents[CurrentMiloRand.GetIntRandom(0, (VectIDArtifactKnowedByThoseAgents.size() - 1))];
//						Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->find(*VectIDArtifactKnowedByThoseAgentsIter);
						Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->find(tmpRandomIDArtifactSelected);
						if(tmpCurrentTabArtifactsIter != tmpCurrentTabArtifacts->end())
						{
							tmpListIDInputs.push_back(tmpCurrentTabArtifactsIter->second.GetID());
							FlagIDArtifactSostitutiveFound = true;
							if(tmpCurrentDebugLevel >= 3)
								cout << "Inserting tmpCurrentTabArtifactsIter->second.GetID(): " << tmpCurrentTabArtifactsIter->second.GetID() << endl;
						}
						VectIDArtifactKnowedByThoseAgentsIter++;
					}
					if(FlagIDArtifactSostitutiveFound == false)
					{
						Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->find(tmpIDInputToAnalize);
						if(tmpCurrentTabArtifactsIter != tmpCurrentTabArtifacts->end())
						{
							tmpListIDInputs.push_back(tmpCurrentTabArtifactsIter->second.GetID());
							if(tmpCurrentDebugLevel >= 3)
								cout << "Inserting tmpCurrentTabArtifactsIter->second.GetID(): " << tmpCurrentTabArtifactsIter->second.GetID() << endl;
						}
						else return(false);
					}
				}
				else 
				{
					Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->find(tmpIDInputToAnalize);
					if(tmpCurrentTabArtifactsIter != tmpCurrentTabArtifacts->end())
					{
						tmpListIDInputs.push_back(tmpCurrentTabArtifactsIter->second.GetID());
						if(tmpCurrentDebugLevel >= 3)
							cout << "Inserting tmpCurrentTabArtifactsIter->second.GetID(): " << tmpCurrentTabArtifactsIter->second.GetID() << endl;
					}
					else return(false);
				}
			}
			list<Mil_Int> tmpListOperators;
			for(list<Mil_Int>::iterator LinksOperatorsIter = tmpCurrentTabRecipesIter->second.LinksOperators.begin(); LinksOperatorsIter != tmpCurrentTabRecipesIter->second.LinksOperators.end(); LinksOperatorsIter++)
			{
				Mil_Int tmpOperatorToAnalize = *LinksOperatorsIter;
				tmpListOperators.push_back(tmpOperatorToAnalize);
			}
			// calculate output of this new recipe
			Mil_Int tmpOutputThisRecipe = CalcOutputThisRecipe(tmpListIDInputs, tmpListOperators, tmpCurrentTabArtifacts, tmpCurrentDebugLevel);
			if(tmpCurrentDebugLevel >= 3)
				cout << "tmpOutputThisRecipe: " << tmpOutputThisRecipe << endl;
			// prepare a vector within the artifacts name that output racipe cannot assume
//			vector<Mil_Int> VectToCompareForOutput;
//			// check if output is into boundaries and its name is different to raw materials
//			tmpOutputThisRecipe = ValidateThisOutputRecipe(tmpCurrentMilovoParam.GetMinNameArtifactAllowed(), tmpCurrentMilovoParam.GetMaxNameArtifactAllowed(), 
//												 VectToCompareForOutput, tmpOutputThisRecipe, 0, tmpCurrentTabAgents, tmpVectIDAgentsToAnalize[0], tmpCurrentDebugLevel);
//			if(tmpOutputThisRecipe != 0)
//			{
//				FlagFoundValidRecipe = true;
				InitGeneticPopulationRecipesFlag = true;
				tmpTabGeneticPopulationRecipes.insert(make_pair(HowManyIndividuals, GeneticRecipe(HowManyIndividuals, tmpOutputThisRecipe, tmpVectIDAgentsToAnalize[0], 15)));
				GeneticRecipes::iterator tmpTabGeneticPopulationRecipesIter = tmpTabGeneticPopulationRecipes.find(HowManyIndividuals);
				if((tmpCurrentDebugLevel >= 0) && tmpTabGeneticPopulationRecipesIter == tmpTabGeneticPopulationRecipes.end())
				{
					cout << "Error in InitGeneticPopulationRecipes function: cannot find tmpTabGeneticPopulationRecipesIter in tmpTabGeneticPopulationRecipes" << endl;
					exit(EXIT_FAILURE);
				}
				for(list<Mil_Int>::iterator tmpListIDInputsIter = tmpListIDInputs.begin(); tmpListIDInputsIter != tmpListIDInputs.end(); tmpListIDInputsIter++)
				{
					Mil_Int tmpIDInputToAnalize = *tmpListIDInputsIter;
					tmpTabGeneticPopulationRecipesIter->second.LinksIDArtifacts.push_back(tmpIDInputToAnalize);
				}
				for(list<Mil_Int>::iterator tmpListOperatorsIter = tmpListOperators.begin(); tmpListOperatorsIter != tmpListOperators.end(); tmpListOperatorsIter++)
				{
					Mil_Int tmpIDOperatorToAnalize = *tmpListOperatorsIter;					
					tmpTabGeneticPopulationRecipesIter->second.LinksOperators.push_back(tmpIDOperatorToAnalize);
				}
//			}
//		}
		
		if(tmpCurrentDebugLevel >= 2)
			cout << "---> Init Genetic Population with individual n." << HowManyIndividuals << "--- [End] --- with tmpRandRecipe: " << tmpRandRecipe << endl;
	}
	if(tmpCurrentDebugLevel >= 2)
		PrintGeneticPopulation(tmpTabGeneticPopulationRecipes, tmpCurrentTabArtifacts);
	
	return(InitGeneticPopulationRecipesFlag);
}

bool InitRandomGeneticPopulationRecipes(MilinitParams &tmpCurrentInitParam, SystemParams &tmpCurrentMilovoParam, GeneticRecipes &tmpTabGeneticPopulationRecipes, 
											 vector<Mil_Int> &tmpVectIDAgentsToAnalize, Agents *tmpCurrentTabAgents, Recipes *tmpCurrentTabRecipes, 
											 Artifacts *tmpCurrentTabArtifacts, MilovoRandom &CurrentMiloRand, int tmpCurrentDebugLevel)
{
	bool InitGeneticPopulationRecipesFlag = false;
	
	vector<Mil_Int> VectIDArtifactKnowedByThoseAgents;
	vector<Mil_Int> VectIDArtifactToDeny;
	for(vector<Mil_Int>::iterator tmpVectIDAgentsToAnalizeIter = tmpVectIDAgentsToAnalize.begin(); tmpVectIDAgentsToAnalizeIter != tmpVectIDAgentsToAnalize.end(); tmpVectIDAgentsToAnalizeIter++)
	{
		Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(*tmpVectIDAgentsToAnalizeIter);
		if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabAgentsIter == tmpCurrentTabAgents->end()))
		{
			Mil_Int tmpCurrentIDAgent = *tmpVectIDAgentsToAnalizeIter;
			cout << "Error in InitGeneticPopulationRecipes function: cannot find tmpCurrentTabAgentsIter in tmpCurrentTabAgents: " << tmpCurrentIDAgent << endl;
			exit(EXIT_FAILURE);
		}
		// check for output recipe produced by this agent
		for(list<Mil_Int>::iterator LinkRecipesIter = tmpCurrentTabAgentsIter->second.LinkRecipes.begin(); LinkRecipesIter != tmpCurrentTabAgentsIter->second.LinkRecipes.end(); LinkRecipesIter++)
		{
			Recipes::iterator tmpCurrentTabRecipesIter = tmpCurrentTabRecipes->find(*LinkRecipesIter);
			if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabRecipesIter == tmpCurrentTabRecipes->end()))
			{
				cout << "Error in InitGeneticPopulationRecipes function: cannot find tmpCurrentTabRecipesIter in tmpCurrentTabRecipes" << endl;
				exit(EXIT_FAILURE);
			}
			VectIDArtifactToDeny.push_back(tmpCurrentTabRecipesIter->second.GetIDArtifactOutput());
			if(tmpCurrentDebugLevel >= 2)
				cout << "Insert in VectIDArtifactToDeny IDOutput: " << tmpCurrentTabRecipesIter->second.GetIDArtifactOutput() << endl;
		}
		if(tmpCurrentDebugLevel >= 2)
			cout << "InitGeneticPopulationRecipes [fill VectRecipeProduced end] for agent: " << tmpCurrentTabAgentsIter->second.GetID() << endl;
	}
	// check for existing artifact knowed by this agent
	for(vector<Mil_Int>::iterator tmpVectIDAgentsToAnalizeIter = tmpVectIDAgentsToAnalize.begin(); tmpVectIDAgentsToAnalizeIter != tmpVectIDAgentsToAnalize.end(); tmpVectIDAgentsToAnalizeIter++)
	{
		Agents::iterator tmpCurrentTabAgentsIter = tmpCurrentTabAgents->find(*tmpVectIDAgentsToAnalizeIter);
		if((tmpCurrentDebugLevel >= 0) && (tmpCurrentTabAgentsIter == tmpCurrentTabAgents->end()))
		{
			Mil_Int tmpCurrentIDAgent = *tmpVectIDAgentsToAnalizeIter;
			cout << "Error in InitGeneticPopulationRecipes function: cannot find tmpCurrentTabAgentsIter in tmpCurrentTabAgents: " << tmpCurrentIDAgent << endl;
			exit(EXIT_FAILURE);
		}
		for(list<Mil_Int>::iterator LinkArtifactsKnowedThisAgentIter = tmpCurrentTabAgentsIter->second.LinkArtifactsKnowed.begin(); LinkArtifactsKnowedThisAgentIter != tmpCurrentTabAgentsIter->second.LinkArtifactsKnowed.end(); LinkArtifactsKnowedThisAgentIter++)
		{
			Artifacts::iterator tmpCurrentTabArtifactsIter = tmpCurrentTabArtifacts->find(*LinkArtifactsKnowedThisAgentIter);
			if(tmpCurrentTabArtifactsIter != tmpCurrentTabArtifacts->end())
			{
				bool FlagDenyArtifactFound = false;
				vector<Mil_Int>::iterator VectIDArtifactToDenyIter = VectIDArtifactToDeny.begin();
				while((FlagDenyArtifactFound == false) && (VectIDArtifactToDenyIter != VectIDArtifactToDeny.end()))
				{
					Mil_Int tmpIDArtifactDenyToCompare = *VectIDArtifactToDenyIter;
					if(tmpCurrentTabArtifactsIter->second.GetID() == tmpIDArtifactDenyToCompare)
						FlagDenyArtifactFound = true;
					else VectIDArtifactToDenyIter++;
				}
				if(FlagDenyArtifactFound == false)
					VectIDArtifactKnowedByThoseAgents.push_back(tmpCurrentTabArtifactsIter->second.GetID());
			}
		}
	}
	// if agent hasn't artifacts knowed or a recipe that it produced before innovation, it cannot try to innovate.
	if((VectIDArtifactKnowedByThoseAgents.empty() == true) || (VectIDArtifactToDeny.empty() == true))
		return(false);
	// create the initial population. First a cycle for every individual of population
	for(Mil_Int HowManyIndividuals = 1; HowManyIndividuals <= tmpCurrentMilovoParam.GetNumGeneticRecipesForInitPopulation(); HowManyIndividuals++)
	{
		list<Mil_Int> tmpListIDInputs;
		Mil_Int HowManyInputArtifacts = CurrentMiloRand.GetIntRandom(tmpCurrentInitParam.GetNumMinArtifactsPerRecipe(), tmpCurrentInitParam.GetNumMaxArtifactsPerRecipe());
		for(Mil_Int HowManyInputArtifactsIndex = 0; HowManyInputArtifactsIndex < HowManyInputArtifacts; HowManyInputArtifactsIndex++)
			tmpListIDInputs.push_back(VectIDArtifactKnowedByThoseAgents[CurrentMiloRand.GetIntRandom(0, (VectIDArtifactKnowedByThoseAgents.size() - 1))]);
		
		list<Mil_Int> tmpListOperators;
		for(Mil_Int HowManyOperators = 0; HowManyOperators < (HowManyInputArtifacts - 1); HowManyOperators++)
			tmpListOperators.push_back(tmpCurrentInitParam.VectOperators[CurrentMiloRand.GetIntRandom(0, (tmpCurrentInitParam.VectOperators.size() - 1))]);
		// calculate output of this new recipe
		Mil_Int tmpOutputThisRecipe = CalcOutputThisRecipe(tmpListIDInputs, tmpListOperators, tmpCurrentTabArtifacts, tmpCurrentDebugLevel);
		InitGeneticPopulationRecipesFlag = true;
		tmpTabGeneticPopulationRecipes.insert(make_pair(HowManyIndividuals, GeneticRecipe(HowManyIndividuals, tmpOutputThisRecipe, tmpVectIDAgentsToAnalize[0], 15)));
		GeneticRecipes::iterator tmpTabGeneticPopulationRecipesIter = tmpTabGeneticPopulationRecipes.find(HowManyIndividuals);
		if((tmpCurrentDebugLevel >= 0) && tmpTabGeneticPopulationRecipesIter == tmpTabGeneticPopulationRecipes.end())
		{
			cout << "Error in InitGeneticPopulationRecipes function: cannot find tmpTabGeneticPopulationRecipesIter in tmpTabGeneticPopulationRecipes" << endl;
			exit(EXIT_FAILURE);
		}
		for(list<Mil_Int>::iterator tmpListIDInputsIter = tmpListIDInputs.begin(); tmpListIDInputsIter != tmpListIDInputs.end(); tmpListIDInputsIter++)
		{
			Mil_Int tmpIDInputToAnalize = *tmpListIDInputsIter;
			tmpTabGeneticPopulationRecipesIter->second.LinksIDArtifacts.push_back(tmpIDInputToAnalize);
		}
		for(list<Mil_Int>::iterator tmpListOperatorsIter = tmpListOperators.begin(); tmpListOperatorsIter != tmpListOperators.end(); tmpListOperatorsIter++)
		{
			Mil_Int tmpIDOperatorToAnalize = *tmpListOperatorsIter;					
			tmpTabGeneticPopulationRecipesIter->second.LinksOperators.push_back(tmpIDOperatorToAnalize);
		}
	}

	return(InitGeneticPopulationRecipesFlag);
}


Mil_Int CalcFitness(GeneticRecipes &tmpTabGeneticPopulationRecipes, Mil_Int tmpSelectedGoal, Artifacts *tmpCurrentTabArtifacts, int tmpCurrentDebugLevel)
{
	if(tmpCurrentDebugLevel >= 3)
		cout << "CalcFitness [begin]" << endl;
	
	vector<Mil_Double> VectMedianForFitness;
	Mil_Double MaxFitness, MedianFitness;
	Mil_Int tmp_IDGeneticRecipeFound = 0;
	for(GeneticRecipes::iterator tmpTabGeneticPopulationRecipesIter = tmpTabGeneticPopulationRecipes.begin(); tmpTabGeneticPopulationRecipesIter != tmpTabGeneticPopulationRecipes.end(); tmpTabGeneticPopulationRecipesIter++)
	{
		list<Mil_Int> tmpListIDInputs;
		for(list<Mil_Int>::iterator LinksIDArtifactsIter = tmpTabGeneticPopulationRecipesIter->second.LinksIDArtifacts.begin(); LinksIDArtifactsIter != tmpTabGeneticPopulationRecipesIter->second.LinksIDArtifacts.end(); LinksIDArtifactsIter++)
		{
			Mil_Int tmpIDInputToAnalize = *LinksIDArtifactsIter;
			tmpListIDInputs.push_back(tmpIDInputToAnalize);
		}
		list<Mil_Int> tmpListOperators;
		for(list<Mil_Int>::iterator LinksOperatorsIter = tmpTabGeneticPopulationRecipesIter->second.LinksOperators.begin(); LinksOperatorsIter != tmpTabGeneticPopulationRecipesIter->second.LinksOperators.end(); LinksOperatorsIter++)
		{
			Mil_Int tmpOperatorToAnalize = *LinksOperatorsIter;
			tmpListOperators.push_back(tmpOperatorToAnalize);
		}
		// calculate output of this new recipe
		Mil_Int tmpOutputThisRecipe = CalcOutputThisRecipe(tmpListIDInputs, tmpListOperators, tmpCurrentTabArtifacts, tmpCurrentDebugLevel);
		tmpTabGeneticPopulationRecipesIter->second.SetOutputName(tmpOutputThisRecipe);
		Mil_Int DeltaGoal = labs(tmpOutputThisRecipe - tmpSelectedGoal);
		if(DeltaGoal == 0)
		{
			tmpTabGeneticPopulationRecipesIter->second.SetFitness(0);
			return(tmpTabGeneticPopulationRecipesIter->second.GetID());
		}
		else tmpTabGeneticPopulationRecipesIter->second.SetFitness(pow(1 / ((Mil_Double) DeltaGoal), 2));
		// calculate the max and median fitness, cause if they are equal the genetic may be stopped.
		if(VectMedianForFitness.empty() == true)
		{
			MaxFitness = tmpTabGeneticPopulationRecipesIter->second.GetFitness();
			VectMedianForFitness.push_back(tmpTabGeneticPopulationRecipesIter->second.GetFitness());
		}
		else
		{
			VectMedianForFitness.push_back(tmpTabGeneticPopulationRecipesIter->second.GetFitness());
			if(MaxFitness < tmpTabGeneticPopulationRecipesIter->second.GetFitness())
				MaxFitness = tmpTabGeneticPopulationRecipesIter->second.GetFitness();
		}
	}
	sort(VectMedianForFitness.begin(), VectMedianForFitness.end());
	if(VectMedianForFitness.size() % 2 == 0)
		MedianFitness = (VectMedianForFitness[(VectMedianForFitness.size() / 2) - 1] + VectMedianForFitness[VectMedianForFitness.size() / 2]) / 2;
	else MedianFitness = VectMedianForFitness[(VectMedianForFitness.size() / 2)];
	
	if(MaxFitness == MedianFitness)
		tmp_IDGeneticRecipeFound = CheckForIDRecipeWithMaxFitness(tmpTabGeneticPopulationRecipes, MaxFitness, tmpCurrentDebugLevel);
	
	if(tmpCurrentDebugLevel >= 3)
		cout << "CalcFitness [end]" << endl;

	return(tmp_IDGeneticRecipeFound);
}

//Mil_Int CalcFitnessTest(GeneticRecipes &tmpTabGeneticPopulationRecipes, Mil_Int tmpSelectedGoal, Artifacts *tmpCurrentTabArtifacts, 
//								Agents *tmpCurrentTabAgent, Mil_Int tmpCurrentIDAgent, int tmpCurrentDebugLevel)
//{
//	if(tmpCurrentDebugLevel >= 3)
//		cout << "CalcFitness [begin]" << endl;
//	
//	vector<Mil_Double> VectMedianForFitness;
//	Mil_Double MaxFitness, MedianFitness;
//	Mil_Int tmp_IDGeneticRecipeFound = 0;
//	for(GeneticRecipes::iterator tmpTabGeneticPopulationRecipesIter = tmpTabGeneticPopulationRecipes.begin(); tmpTabGeneticPopulationRecipesIter != tmpTabGeneticPopulationRecipes.end(); tmpTabGeneticPopulationRecipesIter++)
//	{
//		list<Mil_Int> tmpListIDInputs;
//		for(list<Mil_Int>::iterator LinksIDArtifactsIter = tmpTabGeneticPopulationRecipesIter->second.LinksIDArtifacts.begin(); LinksIDArtifactsIter != tmpTabGeneticPopulationRecipesIter->second.LinksIDArtifacts.end(); LinksIDArtifactsIter++)
//		{
//			Mil_Int tmpIDInputToAnalize = *LinksIDArtifactsIter;
//			tmpListIDInputs.push_back(tmpIDInputToAnalize);
//		}
//		list<Mil_Int> tmpListOperators;
//		for(list<Mil_Int>::iterator LinksOperatorsIter = tmpTabGeneticPopulationRecipesIter->second.LinksOperators.begin(); LinksOperatorsIter != tmpTabGeneticPopulationRecipesIter->second.LinksOperators.end(); LinksOperatorsIter++)
//		{
//			Mil_Int tmpOperatorToAnalize = *LinksOperatorsIter;
//			tmpListOperators.push_back(tmpOperatorToAnalize);
//		}
//		// calculate output of this new recipe
//		Mil_Int tmpOutputThisRecipe = CalcOutputThisRecipe(tmpListIDInputs, tmpListOperators, tmpCurrentTabArtifacts, tmpCurrentDebugLevel);
//		// ******************************************************************************************************************************
//		vector<Mil_Int> VectValuesToComparePippo;
//		tmpOutputThisRecipe = ValidateThisOutputRecipe(1, 1000000, VectValuesToComparePippo, tmpOutputThisRecipe, tmpSelectedGoal, tmpCurrentTabAgent, tmpCurrentIDAgent, 0);
//			// ******************************************************************************************************************************
//			tmpTabGeneticPopulationRecipesIter->second.SetOutputName(tmpOutputThisRecipe);
//		Mil_Int DeltaGoal = labs(tmpOutputThisRecipe - tmpSelectedGoal);
//		if(DeltaGoal == 0)
//		{
//			tmpTabGeneticPopulationRecipesIter->second.SetFitness(0);
//			return(tmpTabGeneticPopulationRecipesIter->second.GetID());
//		}
//		else tmpTabGeneticPopulationRecipesIter->second.SetFitness(pow(1 / ((Mil_Double) DeltaGoal), 2));
//		// calculate the max and median fitness, cause if they are equal the genetic may be stopped.
//		if(VectMedianForFitness.empty() == true)
//		{
//			MaxFitness = tmpTabGeneticPopulationRecipesIter->second.GetFitness();
//			VectMedianForFitness.push_back(tmpTabGeneticPopulationRecipesIter->second.GetFitness());
//		}
//		else
//		{
//			VectMedianForFitness.push_back(tmpTabGeneticPopulationRecipesIter->second.GetFitness());
//			if(MaxFitness < tmpTabGeneticPopulationRecipesIter->second.GetFitness())
//				MaxFitness = tmpTabGeneticPopulationRecipesIter->second.GetFitness();
//		}
//	}
//	sort(VectMedianForFitness.begin(), VectMedianForFitness.end());
//	if(VectMedianForFitness.size() % 2 == 0)
//		MedianFitness = (VectMedianForFitness[(VectMedianForFitness.size() / 2) - 1] + VectMedianForFitness[VectMedianForFitness.size() / 2]) / 2;
//	else MedianFitness = VectMedianForFitness[(VectMedianForFitness.size() / 2)];
//	
//	if(MaxFitness == MedianFitness)
//		tmp_IDGeneticRecipeFound = CheckForIDRecipeWithMaxFitness(tmpTabGeneticPopulationRecipes, MaxFitness, tmpCurrentDebugLevel);
//	
//	if(tmpCurrentDebugLevel >= 3)
//		cout << "CalcFitness [end]" << endl;
//	
//	return(tmp_IDGeneticRecipeFound);
//}

void SelectParents(GeneticRecipes &tmpTabGeneticPopulationRecipes, vector<Mil_Int> &tmpVectParents, MilovoRandom &tmpCurrentMiloRand, int tmpCurrentDebugLevel)
{
	if(tmpCurrentDebugLevel >= 3)
		cout << "SelectParents [begin]" << endl;
	Mil_Double SumFitness = 0.0;
	for(GeneticRecipes::iterator tmpTabGeneticPopulationRecipesIter = tmpTabGeneticPopulationRecipes.begin(); tmpTabGeneticPopulationRecipesIter != tmpTabGeneticPopulationRecipes.end(); tmpTabGeneticPopulationRecipesIter++)
		SumFitness += tmpTabGeneticPopulationRecipesIter->second.GetFitness();

	for(Mil_Int tmpNumParentsIndex = 1; tmpNumParentsIndex <= 2; tmpNumParentsIndex++)
	{
		Mil_Double tmpSelValue = tmpCurrentMiloRand.GetDoubleRandom(0.0, SumFitness);
		bool FlagFound = false;
		Mil_Double tmpSum = 0;
		GeneticRecipes::iterator tmpTabGeneticPopulationRecipesIter = tmpTabGeneticPopulationRecipes.begin();
		while((FlagFound == false) && (tmpTabGeneticPopulationRecipesIter != tmpTabGeneticPopulationRecipes.end()))
		{
			tmpSum += tmpTabGeneticPopulationRecipesIter->second.GetFitness();
			if(tmpSum >= tmpSelValue)
			{
				tmpVectParents.push_back(tmpTabGeneticPopulationRecipesIter->second.GetID());
				FlagFound = true;
				if(tmpCurrentDebugLevel >= 3)
					cout << "tmpVectParents[" << (tmpVectParents.size() - 1) << "]: " << tmpVectParents[tmpVectParents.size() - 1] << endl;
			}
			tmpTabGeneticPopulationRecipesIter++;
		}
	}
	if(tmpCurrentDebugLevel >= 3)
		cout << "SelectParents [end]" << endl;
}

Mil_Int GetCuttingPointThoseRecipes(vector<Mil_Int> &CurrentVectParents, GeneticRecipes &CurrentTabGeneticPopulationRecipes, 
												MilovoRandom &tmp_CurrentMiloRand, int tmp_CurrentDebugLevel)
{
	if(tmp_CurrentDebugLevel >= 2)
		cout << "GetCuttingPointThoseRecipes [begin]" << endl;
	
	Mil_Int ParentWithLessInput = 0;
	Mil_Int HowManyInputThisParent = 0;
	for(vector<Mil_Int>::iterator CurrentVectParentsIter = CurrentVectParents.begin(); CurrentVectParentsIter != CurrentVectParents.end(); CurrentVectParentsIter++)
	{
		GeneticRecipes::iterator CurrentTabGeneticPopulationRecipesIter = CurrentTabGeneticPopulationRecipes.find(*CurrentVectParentsIter);
		if((tmp_CurrentDebugLevel >= 0) && (CurrentTabGeneticPopulationRecipesIter == CurrentTabGeneticPopulationRecipes.end()))
		{
			cout << "Error in GetCuttingPointThoseRecipes function: cannot find CurrentTabGeneticPopulationRecipesIter in CurrentTabGeneticPopulationRecipes" << endl;
			exit(EXIT_FAILURE);
		}
		// searching for genetic recipe with more inputs
		Mil_Int HowManyInput = CurrentTabGeneticPopulationRecipesIter->second.LinksIDArtifacts.size();
		if(HowManyInputThisParent == 0)
		{
			HowManyInputThisParent = HowManyInput;
			ParentWithLessInput = *CurrentVectParentsIter;
		}
		else
		{
			if(HowManyInput < HowManyInputThisParent)
				ParentWithLessInput = *CurrentVectParentsIter;
		}
	}
	// if selected parent 0, that not exist, there is an error
	if((tmp_CurrentDebugLevel >= 0) && (ParentWithLessInput <= 0))
	{
		cout << "Error in GetCuttingPointThoseRecipes function: ParentWithLessInput = " << ParentWithLessInput << endl;
		exit(EXIT_FAILURE);
	}
	GeneticRecipes::iterator CurrentTabGeneticPopulationRecipesIter = CurrentTabGeneticPopulationRecipes.find(ParentWithLessInput);
	Mil_Int HowManyInput = CurrentTabGeneticPopulationRecipesIter->second.LinksIDArtifacts.size();
	Mil_Int tmpCuttingPoint = tmp_CurrentMiloRand.GetIntRandom(1, (HowManyInput - 1));
	if(tmp_CurrentDebugLevel >= 2)
		cout << "GetCuttingPointThoseRecipes [end] -- select tmpCuttingPoint: " << tmpCuttingPoint << endl;

	return(tmpCuttingPoint);
}

void CrossOver(GeneticRecipes &tmpTabGeneticPopulationRecipes, GeneticRecipes &tmpTabTempGeneticPopulationRecipes, vector<Mil_Int> &tmpVectParents, 
					MilovoRandom &tmpCurrentMiloRand, int tmpCurrentDebugLevel)
{
	if(tmpCurrentDebugLevel >= 3)
		cout << "CrossOver [begin]" << endl;
	// calculate catting point
	Mil_Int RecipeCuttingPoint = GetCuttingPointThoseRecipes(tmpVectParents, tmpTabGeneticPopulationRecipes, tmpCurrentMiloRand, tmpCurrentDebugLevel);
	// Father Stuff
	list<Mil_Int> ListArtifactsFatherPreCut;
	list<Mil_Int> ListArtifactsFatherPostCut;
	list<Mil_Int> ListOperatorsFatherPreCut;
	list<Mil_Int> ListOperatorsFatherPostCut;
	CutSelectedRecipesForCrossOver(tmpVectParents[0], tmpTabGeneticPopulationRecipes, ListArtifactsFatherPreCut, ListArtifactsFatherPostCut, 
											 ListOperatorsFatherPreCut, ListOperatorsFatherPostCut, RecipeCuttingPoint, tmpCurrentMiloRand, tmpCurrentDebugLevel);
	// Mother Stuff
	list<Mil_Int> ListArtifactsMotherPreCut;
	list<Mil_Int> ListArtifactsMotherPostCut;
	list<Mil_Int> ListOperatorsMotherPreCut;
	list<Mil_Int> ListOperatorsMotherPostCut;
	CutSelectedRecipesForCrossOver(tmpVectParents[1], tmpTabGeneticPopulationRecipes, ListArtifactsMotherPreCut, ListArtifactsMotherPostCut, 
											 ListOperatorsMotherPreCut, ListOperatorsMotherPostCut, RecipeCuttingPoint, tmpCurrentMiloRand, tmpCurrentDebugLevel);
	// insert in new tmpTabGeneticPopulationRecipes structure, the new recipe
	Mil_Int KeyToInsert = tmpTabTempGeneticPopulationRecipes.size() + 1;
	tmpTabTempGeneticPopulationRecipes.insert(make_pair(KeyToInsert, GeneticRecipe(KeyToInsert, 0, tmpVectParents[0], 15)));
	GeneticRecipes::iterator tmpTabTempGeneticPopulationRecipesIter = tmpTabTempGeneticPopulationRecipes.find(KeyToInsert);
	if((tmpCurrentDebugLevel >= 0) && (tmpTabTempGeneticPopulationRecipesIter == tmpTabTempGeneticPopulationRecipes.end()))
	{
		cout << "Error in CrossOver function: cannot find tmpTabTempGeneticPopulationRecipesIter in tmpTabTempGeneticPopulationRecipes" << endl;
		exit(EXIT_FAILURE);
	}
	// insert input of father pre
	for(list<Mil_Int>::iterator ListArtifactsFatherPreCutIter = ListArtifactsFatherPreCut.begin(); ListArtifactsFatherPreCutIter != ListArtifactsFatherPreCut.end(); ListArtifactsFatherPreCutIter++)
	{
		Mil_Int tmpIDArtifactFatherPreCut = *ListArtifactsFatherPreCutIter;
		tmpTabTempGeneticPopulationRecipesIter->second.LinksIDArtifacts.push_back(tmpIDArtifactFatherPreCut);
	}
	// insert input of mother post
	for(list<Mil_Int>::iterator ListArtifactsMotherPostCutIter = ListArtifactsMotherPostCut.begin(); ListArtifactsMotherPostCutIter != ListArtifactsMotherPostCut.end(); ListArtifactsMotherPostCutIter++)
	{
		Mil_Int tmpIDArtifactMotherPostCut = *ListArtifactsMotherPostCutIter;
		tmpTabTempGeneticPopulationRecipesIter->second.LinksIDArtifacts.push_back(tmpIDArtifactMotherPostCut);
	}
	// insert operator of father pre
	for(list<Mil_Int>::iterator ListOperatorsFatherPreCutIter = ListOperatorsFatherPreCut.begin(); ListOperatorsFatherPreCutIter != ListOperatorsFatherPreCut.end(); ListOperatorsFatherPreCutIter++)
	{
		Mil_Int tmpOperatorFatherPreCut = *ListOperatorsFatherPreCutIter;
		tmpTabTempGeneticPopulationRecipesIter->second.LinksOperators.push_back(tmpOperatorFatherPreCut);
	}
	// insert operator of mother post
	for(list<Mil_Int>::iterator ListOperatorsMotherPostCutIter = ListOperatorsMotherPostCut.begin(); ListOperatorsMotherPostCutIter != ListOperatorsMotherPostCut.end(); ListOperatorsMotherPostCutIter++)
	{
		Mil_Int tmpOperatorMotherPostCut = *ListOperatorsMotherPostCutIter;
		tmpTabTempGeneticPopulationRecipesIter->second.LinksOperators.push_back(tmpOperatorMotherPostCut);
	}
	// insert in new tmpTabGeneticPopulationRecipes structure, the new recipe --------------------------------------------------------------------
	KeyToInsert = tmpTabTempGeneticPopulationRecipes.size() + 1;
	tmpTabTempGeneticPopulationRecipes.insert(make_pair(KeyToInsert, GeneticRecipe(KeyToInsert, 0, tmpVectParents[1], 15)));
	tmpTabTempGeneticPopulationRecipesIter = tmpTabTempGeneticPopulationRecipes.find(KeyToInsert);
	if((tmpCurrentDebugLevel >= 0) && (tmpTabTempGeneticPopulationRecipesIter == tmpTabTempGeneticPopulationRecipes.end()))
	{
		cout << "Error in CrossOver function: cannot find tmpTabTempGeneticPopulationRecipesIter in tmpTabTempGeneticPopulationRecipes" << endl;
		exit(EXIT_FAILURE);
	}
	// insert input of mother pre
	for(list<Mil_Int>::iterator ListArtifactsMotherPreCutIter = ListArtifactsMotherPreCut.begin(); ListArtifactsMotherPreCutIter != ListArtifactsMotherPreCut.end(); ListArtifactsMotherPreCutIter++)
	{
		Mil_Int tmpIDArtifactsMotherPreCut = *ListArtifactsMotherPreCutIter;
		tmpTabTempGeneticPopulationRecipesIter->second.LinksIDArtifacts.push_back(tmpIDArtifactsMotherPreCut);
	}
	// insert input of father post
	for(list<Mil_Int>::iterator ListArtifactsFatherPostCutIter = ListArtifactsFatherPostCut.begin(); ListArtifactsFatherPostCutIter != ListArtifactsFatherPostCut.end(); ListArtifactsFatherPostCutIter++)
	{
		Mil_Int tmpIDArtifactsFatherPostCut = *ListArtifactsFatherPostCutIter;
		tmpTabTempGeneticPopulationRecipesIter->second.LinksIDArtifacts.push_back(tmpIDArtifactsFatherPostCut);
	}
	// input operator of mother pre
	for(list<Mil_Int>::iterator ListOperatorsMotherPreCutIter = ListOperatorsMotherPreCut.begin(); ListOperatorsMotherPreCutIter != ListOperatorsMotherPreCut.end(); ListOperatorsMotherPreCutIter++)
	{
		Mil_Int tmpOperatorMotherPreCut = *ListOperatorsMotherPreCutIter;
		tmpTabTempGeneticPopulationRecipesIter->second.LinksOperators.push_back(tmpOperatorMotherPreCut);
	}
	// insert operator of father post
	for(list<Mil_Int>::iterator ListOperatorsFatherPostCutIter = ListOperatorsFatherPostCut.begin(); ListOperatorsFatherPostCutIter != ListOperatorsFatherPostCut.end(); ListOperatorsFatherPostCutIter++)
	{
		Mil_Int tmpOperatorsFatherPostCut = *ListOperatorsFatherPostCutIter;
		tmpTabTempGeneticPopulationRecipesIter->second.LinksOperators.push_back(tmpOperatorsFatherPostCut);
	}
	if(tmpCurrentDebugLevel >= 3)
		cout << "CrossOver [end]" << endl;
}

void CutSelectedRecipesForCrossOver(Mil_Int tmpIDParent, GeneticRecipes &tmp_TabGeneticPopulationRecipes, list<Mil_Int> &tmpListArtifactsParentPreCut, 
												list<Mil_Int> &tmpListArtifactsParentPostCut, list<Mil_Int> &tmpListOperatorsParentPreCut, list<Mil_Int> &tmpListOperatorsParentPostCut, 
												Mil_Int tmpRecipeCutPoint, MilovoRandom &tmp_CurrentMiloRand, int tmp_CurrentDebugLevel)
{
	GeneticRecipes::iterator tmp_GeneticRecipesParentIter = tmp_TabGeneticPopulationRecipes.find(tmpIDParent);
	if((tmp_CurrentDebugLevel >= 0) && (tmp_GeneticRecipesParentIter == tmp_TabGeneticPopulationRecipes.end()))
	{
		cout << "Error in CutSelectedRecipesForCrossOver function: cannot find tmp_GeneticRecipesParentIter in tmp_TabGeneticPopulationRecipes: " << tmpIDParent << endl;
		exit(EXIT_FAILURE);
	}
	// selecting cutting point. This cutting point may start from fisrt position
	// and must finish before last position. 
//	Mil_Int CuttingPoint = tmp_CurrentMiloRand.GetIntRandom(1, (tmp_GeneticRecipesParentIter->second.LinksIDArtifacts.size() - 1));
	Mil_Int CuttingPoint = tmpRecipeCutPoint;
	Mil_Int CuttingPointIndex = 1;
	for(list<Mil_Int>::iterator LinksIDArtifactsParentIter = tmp_GeneticRecipesParentIter->second.LinksIDArtifacts.begin(); LinksIDArtifactsParentIter != tmp_GeneticRecipesParentIter->second.LinksIDArtifacts.end(); LinksIDArtifactsParentIter++)
	{
		Mil_Int tmpIDArtifactParentToAnalize = *LinksIDArtifactsParentIter;
		if(CuttingPointIndex <= CuttingPoint)
		{
			tmpListArtifactsParentPreCut.push_back(tmpIDArtifactParentToAnalize);
			CuttingPointIndex++;
		}
		else tmpListArtifactsParentPostCut.push_back(tmpIDArtifactParentToAnalize);
	}
	// do it for operators
	CuttingPointIndex = 1;
	for(list<Mil_Int>::iterator LinksOperatorsParentIter = tmp_GeneticRecipesParentIter->second.LinksOperators.begin(); LinksOperatorsParentIter != tmp_GeneticRecipesParentIter->second.LinksOperators.end(); LinksOperatorsParentIter++)
	{
		Mil_Int tmpOperatorParentToAnalize = *LinksOperatorsParentIter;
		if(CuttingPointIndex <= CuttingPoint)
		{
			tmpListOperatorsParentPreCut.push_back(tmpOperatorParentToAnalize);
			CuttingPointIndex++;
		}
		else tmpListOperatorsParentPostCut.push_back(tmpOperatorParentToAnalize);
	}		
}

void UpdateGeneticPopulationRecipes(GeneticRecipes &tmpTabGeneticPopulationRecipes, GeneticRecipes &tmpTabTempGeneticPopulationRecipes, int tmpCurrentDebugLevel)
{
	tmpTabGeneticPopulationRecipes.clear();
	for(GeneticRecipes::iterator tmpTabTempGeneticPopulationRecipesIter = tmpTabTempGeneticPopulationRecipes.begin(); tmpTabTempGeneticPopulationRecipesIter != tmpTabTempGeneticPopulationRecipes.end(); tmpTabTempGeneticPopulationRecipesIter++)
	{
		tmpTabGeneticPopulationRecipes.insert(make_pair(tmpTabTempGeneticPopulationRecipesIter->second.GetID(), 
																		GeneticRecipe(tmpTabTempGeneticPopulationRecipesIter->second.GetID(), 
																						  tmpTabTempGeneticPopulationRecipesIter->second.GetOutputName(), 
																						  tmpTabTempGeneticPopulationRecipesIter->second.GetIDAgentOwner(), 
																						  tmpTabTempGeneticPopulationRecipesIter->second.GetStatus())));
		GeneticRecipes::iterator tmpTabGeneticPopulationRecipesIter = tmpTabGeneticPopulationRecipes.find(tmpTabTempGeneticPopulationRecipesIter->second.GetID());
		if((tmpCurrentDebugLevel >= 0) && (tmpTabGeneticPopulationRecipesIter == tmpTabGeneticPopulationRecipes.end()))
		{
			cout << "Error in UpdateGeneticPopulationRecipes function: cannot find tmpTabGeneticPopulationRecipesIter in tmpTabGeneticPopulationRecipes: " << tmpTabTempGeneticPopulationRecipesIter->second.GetID() << endl;
			exit(EXIT_FAILURE);
		}
		tmpTabGeneticPopulationRecipesIter->second.SetFitness(tmpTabTempGeneticPopulationRecipesIter->second.GetFitness());
		for(list<Mil_Int>::iterator LinksIDArtifactsIter = tmpTabTempGeneticPopulationRecipesIter->second.LinksIDArtifacts.begin(); LinksIDArtifactsIter != tmpTabTempGeneticPopulationRecipesIter->second.LinksIDArtifacts.end(); LinksIDArtifactsIter++)
		{
			Mil_Int tmpIDInputToAnalize = *LinksIDArtifactsIter;
			tmpTabGeneticPopulationRecipesIter->second.LinksIDArtifacts.push_back(tmpIDInputToAnalize);
		}
		for(list<Mil_Int>::iterator LinksOperatorsIter = tmpTabTempGeneticPopulationRecipesIter->second.LinksOperators.begin(); LinksOperatorsIter != tmpTabTempGeneticPopulationRecipesIter->second.LinksOperators.end(); LinksOperatorsIter++)
		{
			Mil_Int tmpOperatorToAnalize = *LinksOperatorsIter;
			tmpTabGeneticPopulationRecipesIter->second.LinksOperators.push_back(tmpOperatorToAnalize);
		}
	}
	tmpTabTempGeneticPopulationRecipes.clear();
}

Mil_Int CheckForIDRecipeWithMaxFitness(GeneticRecipes &CurrentTabGeneticPopulationRecipes, Mil_Double tmpMaxFitness, int tmp_CurrentDebugLevel)
{
	bool FlagFound = false;
	Mil_Int tmpIDRecipeGeneticWithMaxFitness = 0;
	GeneticRecipes::iterator CurrentTabGeneticPopulationRecipesIter = CurrentTabGeneticPopulationRecipes.begin();
	while((FlagFound == false) && (CurrentTabGeneticPopulationRecipesIter != CurrentTabGeneticPopulationRecipes.end()))
	{
		if(CurrentTabGeneticPopulationRecipesIter->second.GetFitness() == tmpMaxFitness)
		{
			tmpIDRecipeGeneticWithMaxFitness = CurrentTabGeneticPopulationRecipesIter->second.GetID();
			FlagFound = true;
		}
		CurrentTabGeneticPopulationRecipesIter++;
	}
	return(tmpIDRecipeGeneticWithMaxFitness);
}



void PrintGeneticPopulation(GeneticRecipes &tmpTabGeneticPopulationRecipes, Artifacts *tmp_CurrentTabArtifacts)
{
	cout << "_______ Genetic Init Population ____________ [Begin] _________" << endl;
	for(GeneticRecipes::iterator tmpTabGeneticPopulationRecipesIter = tmpTabGeneticPopulationRecipes.begin(); tmpTabGeneticPopulationRecipesIter != tmpTabGeneticPopulationRecipes.end(); tmpTabGeneticPopulationRecipesIter++)
	{
		cout << "IDGeneticRecipe: " << tmpTabGeneticPopulationRecipesIter->second.GetID();
		list<Mil_Int>::iterator LinksIDArtifactsIter = tmpTabGeneticPopulationRecipesIter->second.LinksIDArtifacts.begin();
		list<Mil_Int>::iterator LinksOperatorsIter = tmpTabGeneticPopulationRecipesIter->second.LinksOperators.begin();
		while(LinksIDArtifactsIter != tmpTabGeneticPopulationRecipesIter->second.LinksIDArtifacts.end())
		{
			Mil_Int tmpIDArtifactToAnalize = *LinksIDArtifactsIter;
			Artifacts::iterator tmp_CurrentTabArtifactsIter = tmp_CurrentTabArtifacts->find(tmpIDArtifactToAnalize);
			cout << "\tID" << tmpIDArtifactToAnalize << "(" << tmp_CurrentTabArtifactsIter->second.GetName() << ")";
			if(LinksOperatorsIter != tmpTabGeneticPopulationRecipesIter->second.LinksOperators.end())
			{
				Mil_Int tmpIDOperatorToAnalize = *LinksOperatorsIter;
				cout << "\top" << tmpIDOperatorToAnalize;
			}
			LinksIDArtifactsIter++;
			LinksOperatorsIter++;
		}
		list<Mil_Int> tmpListIDInputs;
		for(list<Mil_Int>::iterator LinksIDArtifactsIter = tmpTabGeneticPopulationRecipesIter->second.LinksIDArtifacts.begin(); LinksIDArtifactsIter != tmpTabGeneticPopulationRecipesIter->second.LinksIDArtifacts.end(); LinksIDArtifactsIter++)
		{
			Mil_Int tmpIDInputToAnalize = *LinksIDArtifactsIter;
			tmpListIDInputs.push_back(tmpIDInputToAnalize);
		}
		list<Mil_Int> tmpListOperators;
		for(list<Mil_Int>::iterator LinksOperatorsIter = tmpTabGeneticPopulationRecipesIter->second.LinksOperators.begin(); LinksOperatorsIter != tmpTabGeneticPopulationRecipesIter->second.LinksOperators.end(); LinksOperatorsIter++)
		{
			Mil_Int tmpOperatorToAnalize = *LinksOperatorsIter;
			tmpListOperators.push_back(tmpOperatorToAnalize);
		}
		Mil_Int tmpOutput = CalcOutputThisRecipe(tmpListIDInputs, tmpListOperators, tmp_CurrentTabArtifacts, 0);
		cout << "\t= " << tmpOutput << endl;
	}	
	cout << "_______ Genetic Init Population ____________ [End] _________" << endl;
}


void PrintGeneticPopulationTofile(GeneticRecipes &tmpTabGeneticPopulationRecipes, Artifacts *tmp_CurrentTabArtifacts, 
											 SimulationParams &tmp_CurrentSimulaParam, MilovoEnvironment &tmp_Current_M_Env, Mil_Int tmpGoal, 
											 Mil_Int tmpAgentSelected, Mil_Int tmpNumGeneration)
{
	string StrPrintGeneticPopulationDatFile = tmp_CurrentSimulaParam.GetWorkingDir() + "PrintGeneticPopulation.csv";
	static bool FlagFirst = true;
	ofstream fid_PrintGeneticPopulation;
	if(FlagFirst == true)
	{
		fid_PrintGeneticPopulation.open(StrPrintGeneticPopulationDatFile.c_str(), ios::out);
		FlagFirst = false;
	}
	else fid_PrintGeneticPopulation.open(StrPrintGeneticPopulationDatFile.c_str(), ios::app);
	
	for(GeneticRecipes::iterator tmpTabGeneticPopulationRecipesIter = tmpTabGeneticPopulationRecipes.begin(); tmpTabGeneticPopulationRecipesIter != tmpTabGeneticPopulationRecipes.end(); tmpTabGeneticPopulationRecipesIter++)
	{
		list<Mil_Int>::iterator LinksIDArtifactsIter = tmpTabGeneticPopulationRecipesIter->second.LinksIDArtifacts.begin();
		fid_PrintGeneticPopulation << tmp_Current_M_Env.GetCurrentStep() << "\t" << tmpAgentSelected << "\t" << tmpGoal << "\t"
			<< tmpNumGeneration << "\t" << tmpTabGeneticPopulationRecipesIter->second.GetOutputName() << "\t" << tmpTabGeneticPopulationRecipesIter->second.GetFitness() << endl;
	}
	fid_PrintGeneticPopulation.close();
}

bool CheckThisGoalWithAgentsOutputs(Mil_Int tmpGoalSelected, Mil_Int tmpIDAgentToAnalize, Agents *tmp_CurrentTabAgents, 
												Recipes *tmp_CurrentTabRecipes, Artifacts *tmp_CurrentTabArtifacts, int tmp_CurrentDebugLevel)
{
	Agents::iterator tmp_CurrentTabAgentsIter = tmp_CurrentTabAgents->find(tmpIDAgentToAnalize);
	if((tmp_CurrentDebugLevel >= 0) && (tmp_CurrentTabAgentsIter == tmp_CurrentTabAgents->end()))
	{
		cout << "Error in CheckThisGoalWithAgentsOutputs function: cannot find tmp_CurrentTabAgentsIter in tmp_CurrentTabAgents: " << tmpIDAgentToAnalize << endl;
		exit(EXIT_FAILURE);
	}
	// reaching for an output equal to this goal
	for(list<Mil_Int>::iterator LinkRecipesIter = tmp_CurrentTabAgentsIter->second.LinkRecipes.begin(); LinkRecipesIter != tmp_CurrentTabAgentsIter->second.LinkRecipes.end(); LinkRecipesIter++)
	{
		// extract output artifact of this recipe
		Mil_Int tmpIDRecipeToAnalize = *LinkRecipesIter;
		Recipes::iterator tmp_CurrentTabRecipesIter = tmp_CurrentTabRecipes->find(tmpIDRecipeToAnalize);
		if((tmp_CurrentDebugLevel >= 0) && (tmp_CurrentTabRecipesIter == tmp_CurrentTabRecipes->end()))
		{
			cout << "Error in CheckThisGoalWithAgentsOutputs function: cannot find tmp_CurrentTabRecipesIter in tmp_CurrentTabRecipes: " << tmpIDRecipeToAnalize << endl;
			exit(EXIT_FAILURE);
		}
		Mil_Int tmpIDArtifactToAnalize = tmp_CurrentTabRecipesIter->second.GetIDArtifactOutput();
		// extract output name of this recipe
		Artifacts::iterator tmp_CurrentTabArtifactsIter = tmp_CurrentTabArtifacts->find(tmpIDArtifactToAnalize);
		if((tmp_CurrentDebugLevel >= 0) && (tmp_CurrentTabArtifactsIter == tmp_CurrentTabArtifacts->end()))
		{
			cout << "Error in CheckThisGoalWithAgentsOutputs function: cannot find tmp_CurrentTabArtifactsIter in tmp_CurrentTabArtifacts: " << tmpIDArtifactToAnalize << endl;
			exit(EXIT_FAILURE);
		}
		if(tmp_CurrentTabArtifactsIter->second.GetName() == tmpGoalSelected)
			return false;
	}
	
	return true;
}

vector<Mil_Int> ExtractAgentsOutputsName(Mil_Int tmpCurrentIDAgentToAnalize, Agents *tmp_CurrentTabAgents, Recipes *tmp_CurrentTabRecipes, 
													 Artifacts *tmp_CurrentTabArtifacts, Mil_Int tmp_CurrentDebugLevel)
{
	vector<Mil_Int> tmpVectIDArtifactKnowedByThoseAgents;
	Agents::iterator tmp_CurrentTabAgentsIter = tmp_CurrentTabAgents->find(tmpCurrentIDAgentToAnalize);
	if((tmp_CurrentDebugLevel >= 0) && (tmp_CurrentTabAgentsIter == tmp_CurrentTabAgents->end()))
	{
		cout << "Error in ExtractAgentsOutputName function: cannot found tmp_CurrentTabAgentsIter in tmp_CurrentTabAgents: " << tmpCurrentIDAgentToAnalize << endl;
		exit(EXIT_FAILURE);
	}
	for(list<Mil_Int>::iterator LinkRecipesIter = tmp_CurrentTabAgentsIter->second.LinkRecipes.begin(); LinkRecipesIter != tmp_CurrentTabAgentsIter->second.LinkRecipes.end(); LinkRecipesIter++)
	{
		Recipes::iterator tmp_CurrentTabRecipesIter = tmp_CurrentTabRecipes->find(*LinkRecipesIter);
		if((tmp_CurrentDebugLevel >= 0) && (tmp_CurrentTabRecipesIter == tmp_CurrentTabRecipes->end()))
		{
			cout << "Error in ExtractAgentsOutputName function: cannot found tmp_CurrentTabRecipesIter in tmp_CurrentTabRecipes" << endl;
			exit(EXIT_FAILURE);
		}
		Artifacts::iterator tmp_CurrentTabArtifactsIter = tmp_CurrentTabArtifacts->find(tmp_CurrentTabRecipesIter->second.GetIDArtifactOutput());
		if((tmp_CurrentDebugLevel >= 0) && (tmp_CurrentTabArtifactsIter == tmp_CurrentTabArtifacts->end()))
		{
			cout << "Error in ExtractAgentsOutputName function: cannot found tmp_CurrentTabArtifactsIter in tmp_CurrentTabArtifacts" << endl;
			exit(EXIT_FAILURE);
		}
		tmpVectIDArtifactKnowedByThoseAgents.push_back(tmp_CurrentTabArtifactsIter->second.GetID());
	}
	
	return(tmpVectIDArtifactKnowedByThoseAgents);
}

void SelectGoalFromRequest(vector<Mil_Int> &tmpVectGoalSelectedFromRequest, Mil_Int tmpIDAgentToAnalize, Agents *tmp_CurrentTabAgents, Requests *tmp_CurrentTabRequests, 
									MilovoRandom &tmp_CurrentMiloRand, MilovoEnvironment &tmp_Current_MiloEnv)
{
	Agents::iterator tmp_CurrentTabAgentsIter = tmp_CurrentTabAgents->find(tmpIDAgentToAnalize);
	if((tmp_Current_MiloEnv.GetDebugLevel() >= 0) && (tmp_CurrentTabAgentsIter == tmp_CurrentTabAgents->end()))
	{
		cout << "error in SelectGoalFromRequest funtion: cannot find tmp_CurrentTabAgentsIter in tmp_CurrentTabAgents: " << tmpIDAgentToAnalize << endl;
		exit(EXIT_FAILURE);
	}
	
	for(Relationships::iterator TabRelationshipsIter = tmp_CurrentTabAgentsIter->second.TabRelationships.begin(); TabRelationshipsIter != tmp_CurrentTabAgentsIter->second.TabRelationships.end(); TabRelationshipsIter++)
	{
		Requests::iterator tmp_CurrentTabRequestsIter = tmp_CurrentTabRequests->begin(); 
		while(tmp_CurrentTabRequestsIter != tmp_CurrentTabRequests->end())
		{
			if((tmp_CurrentTabRequestsIter->second.GetIDAgentOwner() == TabRelationshipsIter->second.GetIDAgentPartner()) &&
				(tmp_CurrentTabRequestsIter->second.GetChecked() == false))
				tmpVectGoalSelectedFromRequest.push_back(tmp_CurrentTabRequestsIter->second.GetID());
			tmp_CurrentTabRequestsIter++;
		}
	}
}

// tmpVectGoalSelectedFromRequest.push_back(tmp_CurrentTabRequestsIter->second.GetArtifactName());
